import {
  SettingOutlined,
  VerticalAlignBottomOutlined,
  VerticalAlignMiddleOutlined,
  VerticalAlignTopOutlined,
} from '@ant-design/icons';
import { Button, Checkbox, Popover, Space, Tooltip, Tree } from 'antd';
import { PropsWithChildren, ReactNode, useMemo } from 'react';
import { YmTablePorps } from '.';
export interface ColumnsSettingProps {
  columns?: YmTablePorps<any>['columns'];
  onColumnsChange?(
    columns: NonNullable<YmTablePorps<any>['columns']>,
    info:
      | {
          type: 'move';
          dragKey: React.Key;
          dropKey: React.Key;
        }
      | { type: 'show' }
      | { type: 'fixed' }
      | { type: 'reset' },
  ): void;
}

export function ColumnsSetting({
  columns,
  onColumnsChange,
}: PropsWithChildren<ColumnsSettingProps>) {
  // 无须深度拷贝,根据dataIndex还原数据

  const treeList = useMemo<
    { name: string; treeData: NonNullable<YmTablePorps['columns']> }[]
  >(() => {
    if (columns && columns.length) {
      const fixed_left_arr: NonNullable<YmTablePorps<any>['columns']> = [];
      const fixed_right_arr: NonNullable<YmTablePorps<any>['columns']> = [];
      const fixed_none_arr: NonNullable<YmTablePorps<any>['columns']> = [];

      for (let i = 0; i < columns?.length; i++) {
        let item = columns[i];
        if (item.fixed === 'left') {
          fixed_left_arr.push(item);
        } else if (item.fixed === 'right') {
          fixed_right_arr.push(item);
        } else {
          fixed_none_arr.push(item);
        }
      }
      return [
        {
          name: '固定在左侧',
          treeData: fixed_left_arr,
        },
        {
          name: '不固定',
          treeData: fixed_none_arr,
        },
        {
          name: '固定在右侧',
          treeData: fixed_right_arr,
        },
      ];
    } else {
      return [];
    }
  }, [columns]);

  const isAllChecked = useMemo(() => {
    return !columns?.some((v) => v.hidden === true);
  }, [columns]);

  const isHaflChecked = useMemo(() => {
    return columns?.some((v) => v.hidden !== true) && !isAllChecked;
  }, [isAllChecked, columns]);

  /**放： 移动到指定的位置 */
  const move = (id: React.Key, targetId: React.Key, dropPosition: number) => {
    const newColumns = [...(columns as any[])];
    const findIndex = newColumns.findIndex(
      (columnItem) => columnItem.key === id,
    );
    const targetIndex = newColumns.findIndex(
      (columnItem) => columnItem.key === targetId,
    );
    const isDownWard = dropPosition > findIndex; //向下
    if (findIndex < 0) return;
    const targetItem = newColumns[findIndex];
    newColumns.splice(findIndex, 1);

    if (dropPosition === 0) {
      newColumns.unshift(targetItem); // 首端添加
    } else {
      newColumns.splice(
        isDownWard ? targetIndex : targetIndex + 1,
        0,
        targetItem,
      );
    }
    // console.log('---move---newColumns---:', newColumns);
    // 重新生成排序数组
    onColumnsChange?.([...newColumns], {
      type: 'move',
      dragKey: id,
      dropKey: targetId,
    });
  };

  return (
    <Popover
      placement="bottomRight"
      trigger={['click']}
      title={
        <div
          style={{ display: 'flex', justifyContent: 'space-between' }}
          hidden={!treeList.length}
        >
          <div>
            <Checkbox
              checked={isAllChecked}
              indeterminate={isHaflChecked}
              onClick={() => {
                if (columns) {
                  onColumnsChange?.(
                    columns.map((v) => {
                      return {
                        ...v,
                        hidden: isAllChecked,
                      };
                    }),
                    { type: 'show' },
                  );
                }
              }}
            >
              列展示
            </Checkbox>
          </div>
          <div>
            <a
              onClick={() => {
                onColumnsChange?.(
                  (columns || []).map((v) => ({ ...v })),
                  {
                    type: 'reset',
                  },
                );
              }}
            >
              重置
            </a>
          </div>
        </div>
      }
      content={
        <ul style={{ listStyle: 'none', padding: 0 }}>
          {treeList.map(({ treeData, name }, index, self) => {
            if (treeData.length === 0) {
              return null;
            }

            return (
              <li key={name}>
                <div style={{ textIndent: 24, marginTop: 6, marginBottom: 6 }}>
                  {name}
                </div>
                <Tree
                  itemHeight={24}
                  draggable={
                    treeData.length > 1 || {
                      icon: (
                        <span
                          style={{
                            display: 'inline-block',
                            width: 24,
                            height: 24,
                          }}
                        ></span>
                      ),
                      nodeDraggable() {
                        return false;
                      },
                    }
                  }
                  virtual={false}
                  selectable={true}
                  selectedKeys={[]}
                  onDrop={(info) => {
                    const dropKey = info.node.key;
                    const dragKey = info.dragNode.key;
                    const { dropPosition, dropToGap } = info;
                    const position =
                      dropPosition === -1 || !dropToGap
                        ? dropPosition + 1
                        : dropPosition;
                    move(dragKey, dropKey, position);
                  }}
                  blockNode
                  showLine={false}
                  titleRender={(node) => {
                    let title: ReactNode | null;
                    if (typeof node.title === 'undefined') {
                      title = null;
                    } else if (typeof node.title === 'function') {
                      title = node.title({});
                    } else {
                      title = node.title;
                    }

                    // 需要知道当前 node 是属于那个范畴的
                    function onClick(
                      e: React.MouseEvent<HTMLSpanElement, MouseEvent>,
                      n: number,
                    ) {
                      e.stopPropagation();
                      e.preventDefault();

                      let delIndex = treeData.findIndex(
                        (v) => v.key === node.key,
                      );
                      let item = treeData.splice(delIndex, 1)[0];
                      item.fixed =
                        n === 0 ? 'left' : n === 1 ? undefined : 'right';
                      if (n === 1 && index === 0) {
                        self[n].treeData.unshift(item);
                      } else {
                        self[n].treeData.push(item);
                      }
                      let newColumns = self.map((v) => v.treeData).flat();
                      onColumnsChange?.(newColumns, {
                        type: 'fixed',
                      });
                    }

                    return (
                      <>
                        <Checkbox checked={node.hidden !== true}>
                          {title}
                        </Checkbox>
                        <Space size={4}>
                          {index !== 0 ? (
                            <Tooltip title="固定在列首">
                              <VerticalAlignTopOutlined
                                onClick={(e) => onClick(e, 0)}
                              />
                            </Tooltip>
                          ) : null}
                          {index !== 1 ? (
                            <Tooltip title="不固定">
                              <VerticalAlignMiddleOutlined
                                onClick={(e) => onClick(e, 1)}
                              />
                            </Tooltip>
                          ) : null}
                          {index !== 2 ? (
                            <Tooltip title="固定在列尾">
                              <VerticalAlignBottomOutlined
                                onClick={(e) => onClick(e, 2)}
                              />
                            </Tooltip>
                          ) : null}
                        </Space>
                      </>
                    );
                  }}
                  onSelect={(e) => {
                    if (columns) {
                      const item = columns.find((v) => v.key === e[0]);
                      if (item) {
                        item.hidden = item.hidden === true ? false : true;
                        onColumnsChange?.(columns.slice(), { type: 'show' });
                      }
                    }
                  }}
                  height={300} // tree maxHeight
                  treeData={treeData}
                />
              </li>
            );
          })}
        </ul>
      }
    >
      <Tooltip title="列设置" destroyTooltipOnHide>
        <Button icon={<SettingOutlined />}></Button>
      </Tooltip>
    </Popover>
  );
}
